﻿using System;
using System.Runtime.Serialization;
using System.Xml;
using System.Linq;
using System.IO;
using System.Text;
using System.Xml.Linq;
using System.Runtime.Serialization.Json;
using System.Reflection;
using System.Xml.Serialization;

namespace Code5Systems.ClientFramework
{
	public class SerializationHelper
	{
		#region XML Serialization

		[Obfuscation(Feature = "cw symbol renaming", Exclude = true)]
		public static string Serialize<T>(T toSerialize, bool removeNS = false)
		{
			string serialized = String.Empty;
			DataContractSerializer itemSerializer;
			try
			{
				// Create a serializer.
				if (typeof(T).IsInterface)
				{
					itemSerializer = new DataContractSerializer(toSerialize.GetType());
				}
				else
				{
					itemSerializer = new DataContractSerializer(typeof(T));
				}

				using (MemoryStream mem = new MemoryStream())
				{
					itemSerializer.WriteObject(mem, toSerialize);
					serialized = Encoding.UTF8.GetString(mem.ToArray(), 0, (int)mem.Length);
					if (removeNS)
					{
						serialized = RemoveAllNamespaces(serialized);
					}
				}
			}
			catch
			{ throw; }

			return serialized;
		}

		[Obfuscation(Feature = "cw symbol renaming", Exclude = true)]
		public static T Deserialize<T>(string serialized)
		{
			DataContractSerializer itemSerializer = new DataContractSerializer(typeof(T));
			XmlReader reader = XmlReader.Create(new StringReader(serialized));
			return (T)itemSerializer.ReadObject(reader);
		}

		[Obfuscation(Feature = "cw symbol renaming", Exclude = true)]
		public static string XmlSerialize<T>(T toSerialize, XmlSerializerNamespaces ns = null) where T : class
		{
			string serialized = String.Empty;

			try
			{
				XmlSerializer serializer = new XmlSerializer(typeof(T));
				MemoryStream mem = new MemoryStream();
				serializer.Serialize(mem, toSerialize, ns);
				serialized = Encoding.UTF8.GetString(mem.ToArray(), 0, (int)mem.Length);
				mem.Close();
			}
			catch
			{ throw; }
			return serialized;
		}

		[Obfuscation(Feature = "cw symbol renaming", Exclude = true)]
		public static T XmlDeserialize<T>(string toDeserialize, string rootElement = "") where T : class
		{
			XmlSerializer serializer = new XmlSerializer(typeof(T), rootElement);
			T deserialized = (T)serializer.Deserialize(System.Xml.XmlReader.Create(new StringReader(toDeserialize)));
			return deserialized;
		}

		//[Obfuscation(Feature = "cw symbol renaming", Exclude = true)]
		//public static string SerializeAndCompress<T>(T toSerialize, bool removeNS = false)
		//{
		//    string serialized = String.Empty;

		//    try
		//    {
		//        serialized = Serialize<byte[]>(MiscHelper.CompressString(Serialize<T>(toSerialize, removeNS)), removeNS);
		//    }
		//    catch
		//    { }

		//    return serialized;
		//}

		//public static T DeCompressAndDeserialize<T>(string compressed)
		//{
		//    return Deserialize<T>(MiscHelper.DeCompressString(Deserialize<byte[]>(compressed)));
		//}

		public static string RemoveAllNamespaces(string xmlDocument)
		{
			XElement xmlDocumentWithoutNs = RemoveAllNamespaces(XElement.Parse(xmlDocument));

			return xmlDocumentWithoutNs.ToString();
		}

		//Core recursion function
		private static XElement RemoveAllNamespaces(XElement xmlDocument)
		{
			if (!xmlDocument.HasElements)
			{
				XElement xElement = new XElement(xmlDocument.Name.LocalName);
				xElement.Value = xmlDocument.Value;
				return xElement;
			}
			return new XElement(xmlDocument.Name.LocalName, xmlDocument.Elements().Select(el => RemoveAllNamespaces(el)));
		}

		#endregion

		#region JSON Serialization

		[Obfuscation(Feature = "cw symbol renaming", Exclude = true)]
		public static string JsonSerialize<T>(T toSerialize)
		{
			string serialized = String.Empty;
			DataContractJsonSerializer itemSerializer;
			try
			{
				// Create a serializer.
				if (typeof(T).IsInterface)
				{
					itemSerializer = new DataContractJsonSerializer(toSerialize.GetType());
				}
				else
				{
					itemSerializer = new DataContractJsonSerializer(typeof(T));
				}

				using (MemoryStream mem = new MemoryStream())
				{
					itemSerializer.WriteObject(mem, toSerialize);
					serialized = Encoding.UTF8.GetString(mem.ToArray(), 0, (int)mem.Length);
				}
			}
			catch
			{ throw; }

			return serialized;
		}

		[Obfuscation(Feature = "cw symbol renaming", Exclude = true)]
		public static T JsonDeserialize<T>(string serialized)
		{
			T item = default(T);
			DataContractJsonSerializer itemSerializer = new DataContractJsonSerializer(typeof(T));

			using (MemoryStream mem = new MemoryStream(Encoding.UTF8.GetBytes(serialized)))
			{
				item = (T)itemSerializer.ReadObject(mem);
			}
			return item;
		}

		#endregion

	}
}
